"""
@author:王耀
@date:2021/9/21
"""
import cv2
import numpy as np

def getGaussKernal(size, dsigma, center):
    """
    作用：获得高斯滤波核
    size(int): kernal的大小
    dsigma(double): 空间域方差
    center(int): size // 2

    返回(numpy.array)：高斯滤波kernal
    """
    # 计算滤波核
    kernel = np.zeros((size, size), dtype=np.float)
    for i in range(-center, -center + size):
        for j in range(-center, -center + size):
            kernel[j + center, i + center] = np.exp(-(i ** 2 + j ** 2) / (2 * (dsigma ** 2)))

    # 归一化
    kernel = kernel / kernel.sum()
    return kernel

def getAlphaTrimmedMeanKernal(res, size, rsigma, center):
    """
    作用：获得alpha-截尾均值滤波核
    res:需要获得滤波器的图片窗口
    size(int): kernal的大小
    rsigma(double): 值域方差
    center(int): size // 2

    返回(numpy.array)：高斯滤波kernal
    """
    kernel = np.zeros((size, size), dtype=np.float)
    for i in range(size):
        for j in range(size):
            kernel[i, j] = np.exp(-((res[center,center] - res[i,j])**2) / (2 * (rsigma ** 2)))
    kernel = kernel / kernel.sum()
    return kernel



def BilateralFilter(img, size = 9, dsigma = 0.01, rsigma = 0.03):
    """
    作用：双边滤波核心代码
    img：输入的图片
    size(int)：滤波大小
    ksigma(double)：（空间域）高斯函数标准差
    rsigma(double): (值域)标准差

    返回：滤波后的图片
    """
    if img is None:
        raise Exception('input image ERROR!')
    if len(img.shape) == 2:
        H, W = img.shape
    else:
        raise Exception('RBG images cannot be entered in Bilateral Filter at this time!')

    center = size // 2
    # 获得高斯核
    gaussKernel = getGaussKernal(size, dsigma, center)

    res = np.zeros((H + center * 2, W + center * 2), dtype=np.float)  #res比img在外面多了center圈
    res[center: center + H, center: center + W] = img.copy().astype(np.float)
    restmp = res.copy()

    for h in range(H):
        for w in range(W):
            # 获得当前窗口内的alpha-尾截均值滤波
            alphaTMkernel = getAlphaTrimmedMeanKernal(restmp[h: h + size, w: w + size], size, rsigma, center)
            # 对应元素相乘
            kernel = np.multiply(alphaTMkernel, gaussKernel)
            # 归一化
            kernel = kernel / kernel.sum()
            # 滤波
            res[center + h, center + w] = np.sum(kernel * restmp[h: h + size, w: w + size])

    res = np.clip(res, 0, 255)
    res = res[center: center + H, center: center + W].astype(np.uint8)

    print('执行完毕：双边滤波')

    return res
